/* 
 * RuleUtil.java
 * 
 * Data de criação: 12/02/2010
 * 
 * O2SOLUTIONS - SOLUÇÕES EM TECNOLOGIA DA INFORMAÇÃO. 
 *
 */
package br.com.o2solutions.core.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import br.com.o2solutions.core.exception.CoreException;
import br.com.o2solutions.core.exception.SystemException;
import br.com.o2solutions.core.service.rule.Rule;
import br.com.o2solutions.util.assertion.Assert;

/**
 * Classe utilitária para aplicação de Regras Negociais.
 * 
 * @author osvaldeir
 * @since 12/02/2010
 * 
 */
public class RuleUtil {

	private static ConfigurableListableBeanFactory beanFactory;

	/**
	 * Realiza a aplicação de uma regra através da classe que aplica tal
	 * operação ao argumento.
	 * 
	 * @param <T>
	 *            Tipo generico para ser aplicada a Regra da Rule
	 * @param rule
	 *            Class da Rule que aplicará a regra.
	 * @param argument
	 *            Tipo a receber a aplicação da Regra.
	 * @throws Exception
	 *             Caso alguma falha aconteça.
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> void applyRule(Class<? extends Rule<?>> rule,
			Object argument) throws Exception {
		Rule newInstance;
		try {
			Assert.notNull(
					beanFactory,
					"Contexto do Spring não encontrado. Verifique se existe a referencia [classpath:/mte-core-application.xml] na configuração do Spring");
			try {
				newInstance = beanFactory.getBean(rule);
				newInstance.check(argument);
			} catch (BeansException e) {
				throw new SystemException(
						"A rule "
								.concat(rule.getName())
								.concat(" não é um bean relacionado no contexto do Spring. Cadastre-o no xml ou insira a anotação @Component na classe."));
			}
		} catch (CoreException e) {
			throw e;
		} catch (Throwable e) {
			throw new SystemException("Erro ao realizar aplicacao da rule", e);
		}

	}

	/**
	 * Retorna o BeanFactory
	 * 
	 * @return the beanFactory
	 */
	public ConfigurableListableBeanFactory getBeanFactory() {
		return beanFactory;
	}

	/**
	 * Atribui o BeanFactory
	 * 
	 * @param beanFactory
	 *            the beanFactory to set
	 */
	@Autowired
	public void setBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		RuleUtil.beanFactory = beanFactory;
	}

}
